package com.wwg.threads.binghe.concurrent.executor.unsafe;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class DateFormatterSafeTest {
    private static final int EXECUTE_NUM = 1000;
    private static final int EXECUTE_THREAD_NUM = 20;

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    private static Lock lock = new ReentrantLock();

    // threadLocal 方式
//    private static ThreadLocal<DateFormat> dateFormatThreadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
    private static ThreadLocal<DateFormat> dateFormatThreadLocal = new ThreadLocal<>();

    static DateFormat getDateFormatter() {
        DateFormat dateFormat = dateFormatThreadLocal.get();
        if (dateFormat == null) {
            dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            dateFormatThreadLocal.set(dateFormat);
        }
        return dateFormat;
    }

    ;

    public static void main(String[] args) {
        // 限制 最多EXECUTE_THREAD_NUM个线程执行
        final Semaphore semaphore = new Semaphore(EXECUTE_THREAD_NUM); //   Semaphore类可以理解为一个计数信号量，必须由获取它的线程释放，经常用来限制访问某些资源的线程数量，例如限流等
        final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_NUM);//  使一个线程等待其他线程各自执行完毕后再执行
        ExecutorService executorService = Executors.newCachedThreadPool();// 线程池
        AtomicInteger errorCount = new AtomicInteger();
        for (int i = 0; i < EXECUTE_NUM; i++) {
            executorService.execute(() -> {
                try {
                    semaphore.acquire();// 线程获取
                    try {

                        /**
                         * 1. 局部变量方式 解决线程安全问题
                         * 2. synchronized 方式
                         * 3. lock 方式
                         */

                        // 1. 局部变量方式
//                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                        simpleDateFormat.parse("2014-05-08");

                        // 2. synchronized 方式
//                        synchronized (simpleDateFormat) {
//                            simpleDateFormat.parse("2014-05-08");
//                        }

                        // 3. lock 方式
//                        lock.lock();
//                        simpleDateFormat.parse("2014-05-08");

                        // 4. threadLocal 方式
//                        dateFormatThreadLocal.get().parse("2014-05-08");
//                        getDateFormatter().parse("2014-05-02");

                    } catch (Exception e) {
                        System.out.println("线程：" + Thread.currentThread().getName() + "格式化日期失败！失败数：" + errorCount.getAndIncrement());
                    }
                    // 3 lock 方式
//                    finally {
//                        lock.unlock();
//                    }

                    semaphore.release();// 线程释放
                } catch (InterruptedException e) {
                    System.out.println("信号量发生错误");
                    e.printStackTrace();
                }
                countDownLatch.countDown();// 记录执行完成计数
            });
        }
        try {
            countDownLatch.await();// 等待全部执行完成
//            executorService.shutdown();
            if (0 == errorCount.get()) {
                System.out.println("所有线程格式化日期成功！");
            }else{
                System.out.println("有异常发生，需要回滚！");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }

}
